using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Parameters;

public class SM4Helper
{
    // SM4加密(ECB模式)
    public static byte[] EncryptECB(byte[] key, byte[] plaintext)
    {
        var engine = new SM4Engine();
        var cipher = new PaddedBufferedBlockCipher(engine, new Pkcs7Padding());
        cipher.Init(true, new KeyParameter(key));

        byte[] output = new byte[cipher.GetOutputSize(plaintext.Length)];
        int len = cipher.ProcessBytes(plaintext, 0, plaintext.Length, output, 0);
        cipher.DoFinal(output, len);

        return output;
    }

    // SM4解密(ECB模式)
    public static byte[] DecryptECB(byte[] key, byte[] ciphertext)
    {
        var engine = new SM4Engine();
        var cipher = new PaddedBufferedBlockCipher(engine, new Pkcs7Padding());
        cipher.Init(false, new KeyParameter(key));

        byte[] output = new byte[cipher.GetOutputSize(ciphertext.Length)];
        int len = cipher.ProcessBytes(ciphertext, 0, ciphertext.Length, output, 0);
        cipher.DoFinal(output, len);

        return output;
    }

    // SM4加密(CBC模式)
    public static byte[] EncryptCBC(byte[] key, byte[] iv, byte[] plaintext)
    {
        var engine = new SM4Engine();
        var cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), new Pkcs7Padding());
        cipher.Init(true, new ParametersWithIV(new KeyParameter(key), iv));

        byte[] output = new byte[cipher.GetOutputSize(plaintext.Length)];
        int len = cipher.ProcessBytes(plaintext, 0, plaintext.Length, output, 0);
        cipher.DoFinal(output, len);

        return output;
    }

    // SM4解密(CBC模式)
    public static byte[] DecryptCBC(byte[] key, byte[] iv, byte[] ciphertext)
    {
        var engine = new SM4Engine();
        var cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), new Pkcs7Padding());
        cipher.Init(false, new ParametersWithIV(new KeyParameter(key), iv));

        byte[] output = new byte[cipher.GetOutputSize(ciphertext.Length)];
        int len = cipher.ProcessBytes(ciphertext, 0, ciphertext.Length, output, 0);
        cipher.DoFinal(output, len);

        return output;
    }
}
